package com.web3.management.security;

import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;

import java.util.Objects;

/**
 * 安全工具类
 */
public final class SecurityUtils {

    private static final String ROLE_ADMIN = "ROLE_ADMIN";
    private static final String ROLE_ACCOUNT_CLIENT = "ROLE_ACCOUNT_CLIENT";

    private SecurityUtils() {
    }

    public static Authentication getAuthentication() {
        return SecurityContextHolder.getContext().getAuthentication();
    }

    public static boolean isAuthenticated() {
        return getAuthentication() != null && getAuthentication().isAuthenticated();
    }

    public static boolean hasRole(String role) {
        Authentication authentication = getAuthentication();
        if (authentication == null) {
            return false;
        }
        for (GrantedAuthority authority : authentication.getAuthorities()) {
            if (role.equals(authority.getAuthority())) {
                return true;
            }
        }
        return false;
    }

    public static boolean isAdmin() {
        return hasRole(ROLE_ADMIN);
    }

    public static boolean isAccountClient() {
        return hasRole(ROLE_ACCOUNT_CLIENT);
    }

    public static AccountClientPrincipal getAccountClientPrincipal() {
        if (!isAccountClient()) {
            return null;
        }
        Object principal = getAuthentication().getPrincipal();
        if (principal instanceof AccountClientPrincipal) {
            return (AccountClientPrincipal) principal;
        }
        return null;
    }

    public static void checkAccountAccess(Integer accountId) {
        if (!isAccountClient()) {
            return;
        }
        AccountClientPrincipal principal = getAccountClientPrincipal();
        if (principal == null || !Objects.equals(principal.getAccountId(), accountId)) {
            throw new AccessDeniedException("无权访问其他账号数据");
        }
    }

    public static void requireAdmin() {
        if (!isAdmin()) {
            throw new AccessDeniedException("仅管理员可执行该操作");
        }
    }
}
